package com.dms.modules.message.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dms.modules.message.dto.MessageDTO;
import com.dms.modules.message.dto.MessageDetailDTO;
import com.dms.modules.message.entity.SystemMessage;
import com.dms.modules.message.entity.UserMessage;
import com.dms.modules.message.mapper.SystemMessageMapper;
import com.dms.modules.message.mapper.UserMessageMapper;
import com.dms.modules.message.service.MessageService;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MessageServiceImpl implements MessageService {

    private final Gson gson = new Gson();

    @Autowired
    private SystemMessageMapper systemMessageMapper;

    @Autowired
    private UserMessageMapper userMessageMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long sendMessage(MessageDTO messageDTO) {
        try {
            // 1. 保存系统消息
            SystemMessage systemMessage = new SystemMessage();
            BeanUtils.copyProperties(messageDTO, systemMessage);
            systemMessage.setTargetIds(gson.toJson(messageDTO.getTargetIds()));
            systemMessage.setStatus(1); // 设置为已发送
            systemMessage.setCreateTime(LocalDateTime.now());
            systemMessage.setUpdateTime(LocalDateTime.now());
            systemMessageMapper.insert(systemMessage);

            // 2. 创建用户消息关联
            List<UserMessage> userMessages = new ArrayList<>();
            
            if (messageDTO.getTargetType() == 1) {
                // TODO: 全部用户，需要查询所有用户ID
            } else if (messageDTO.getTargetType() == 2 && messageDTO.getTargetIds() != null) {
                // 指定用户
                userMessages = messageDTO.getTargetIds().stream().map(userId -> {
                    UserMessage userMessage = new UserMessage();
                    userMessage.setUserId(userId);
                    userMessage.setMessageId(systemMessage.getId());
                    userMessage.setIsRead(0);
                    userMessage.setCreateTime(LocalDateTime.now());
                    return userMessage;
                }).collect(Collectors.toList());
            } else if (messageDTO.getTargetType() == 3 && messageDTO.getTargetIds() != null) {
                // TODO: 指定角色，需要查询角色下的用户ID
            }

            if (!userMessages.isEmpty()) {
                userMessageMapper.batchInsert(userMessages);
            }

            return systemMessage.getId();
        } catch (Exception e) {
            log.error("发送消息失败: {}", e.getMessage(), e);
            throw e;
        }
    }

    @Override
    public IPage<MessageDetailDTO> getUserMessages(Long userId, Integer type, Page<MessageDetailDTO> page) {
        try {
            // 1. 查询用户的消息关联
            LambdaQueryWrapper<UserMessage> userMessageWrapper = new LambdaQueryWrapper<>();
            userMessageWrapper.eq(UserMessage::getUserId, userId)
                            .orderByDesc(UserMessage::getCreateTime);

            Page<UserMessage> userMessagePage = new Page<>(page.getCurrent(), page.getSize());
            IPage<UserMessage> userMessageResult = userMessageMapper.selectPage(userMessagePage, userMessageWrapper);

            // 2. 查询消息详情
            List<MessageDetailDTO> records = userMessageResult.getRecords().stream()
                .map(userMessage -> {
                    SystemMessage systemMessage = systemMessageMapper.selectById(userMessage.getMessageId());
                    if (systemMessage != null && (type == null || systemMessage.getType().equals(type))) {
                        MessageDetailDTO detailDTO = new MessageDetailDTO();
                        BeanUtils.copyProperties(systemMessage, detailDTO);
                        
                        // 处理targetIds的类型转换
                        try {
                            List<?> rawIds = gson.fromJson(systemMessage.getTargetIds(), List.class);
                            if (rawIds != null) {
                                List<Long> longIds = rawIds.stream()
                                    .map(id -> {
                                        if (id instanceof Double) {
                                            return ((Double) id).longValue();
                                        } else if (id instanceof Integer) {
                                            return ((Integer) id).longValue();
                                        } else if (id instanceof Long) {
                                            return (Long) id;
                                        } else if (id instanceof String) {
                                            return Long.parseLong((String) id);
                                        }
                                        return null;
                                    })
                                    .filter(id -> id != null)
                                    .collect(Collectors.toList());
                                detailDTO.setTargetIds(longIds);
                            }
                        } catch (Exception e) {
                            log.warn("解析targetIds失败: {}", systemMessage.getTargetIds(), e);
                            detailDTO.setTargetIds(new ArrayList<>());
                        }
                        
                        detailDTO.setIsRead(userMessage.getIsRead() == 1);
                        detailDTO.setReadTime(userMessage.getReadTime());
                        return detailDTO;
                    }
                    return null;
                })
                .filter(java.util.Objects::nonNull)
                .collect(Collectors.toList());

            // 3. 构建返回结果
            IPage<MessageDetailDTO> result = new Page<>(page.getCurrent(), page.getSize(), userMessageResult.getTotal());
            result.setRecords(records);
            return result;
        } catch (Exception e) {
            log.error("获取用户消息列表失败: userId={}, type={}, error={}", userId, type, e.getMessage(), e);
            throw e;
        }
    }

    @Override
    public MessageDetailDTO getMessageDetail(Long userId, Long messageId) {
        try {
            // 1. 查询消息
            SystemMessage systemMessage = systemMessageMapper.selectById(messageId);
            if (systemMessage == null) {
                return null;
            }

            // 2. 查询用户消息关联
            LambdaQueryWrapper<UserMessage> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UserMessage::getUserId, userId)
                   .eq(UserMessage::getMessageId, messageId);
            UserMessage userMessage = userMessageMapper.selectOne(wrapper);
            if (userMessage == null) {
                return null;
            }

            // 3. 构建返回结果
            MessageDetailDTO detailDTO = new MessageDetailDTO();
            BeanUtils.copyProperties(systemMessage, detailDTO);
            detailDTO.setTargetIds(gson.fromJson(systemMessage.getTargetIds(), List.class));
            detailDTO.setIsRead(userMessage.getIsRead() == 1);
            detailDTO.setReadTime(userMessage.getReadTime());
            
            return detailDTO;
        } catch (Exception e) {
            log.error("获取消息详情失败: userId={}, messageId={}, error={}", userId, messageId, e.getMessage(), e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean markAsRead(Long userId, Long messageId) {
        try {
            LambdaQueryWrapper<UserMessage> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UserMessage::getUserId, userId)
                   .eq(UserMessage::getMessageId, messageId)
                   .eq(UserMessage::getIsRead, 0);

            UserMessage userMessage = new UserMessage();
            userMessage.setIsRead(1);
            userMessage.setReadTime(LocalDateTime.now());

            return userMessageMapper.update(userMessage, wrapper) > 0;
        } catch (Exception e) {
            log.error("标记消息已读失败: userId={}, messageId={}, error={}", userId, messageId, e.getMessage(), e);
            throw e;
        }
    }

    @Override
    public int getUnreadCount(Long userId) {
        try {
            return userMessageMapper.selectUnreadCount(userId);
        } catch (Exception e) {
            log.error("获取未读消息数失败: userId={}, error={}", userId, e.getMessage(), e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean recallMessage(Long messageId) {
        try {
            SystemMessage message = new SystemMessage();
            message.setId(messageId);
            message.setStatus(2); // 设置为已撤回
            message.setUpdateTime(LocalDateTime.now());
            
            return systemMessageMapper.updateById(message) > 0;
        } catch (Exception e) {
            log.error("撤回消息失败: messageId={}, error={}", messageId, e.getMessage(), e);
            throw e;
        }
    }
} 